package com.program.facesigninsystem.controller;

import cn.yueshutong.springbootstartercurrentlimiting.annotation.CurrentLimiter;
import com.alibaba.fastjson.JSONObject;
import com.arcsoft.face.FaceFeature;
import com.arcsoft.face.FaceInfo;
import com.program.facesigninsystem.entity.*;
import com.program.facesigninsystem.face.ArcSoftFace;
import com.program.facesigninsystem.service.*;
import com.program.facesigninsystem.util.*;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.*;
import java.util.*;



/**
 * @author Mapler
 */
@CrossOrigin
@RestController
@RequestMapping(value = "/auth")
public class UserController {
    private ArcSoftFace arcSoftFace = new ArcSoftFace();

    @Resource
    public IUserInfoService iUserInfoService;

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @CurrentLimiter(QPS = 5)
    public ResponseModel loginUser(@RequestBody JSONObject account) {
        int length = 20;
        final String appId = "wx0f5fe820060cfca1";
        final String secret = "68a829ffe7ac81fe570b4318be384200";
        ResponseModel responseModel;
        String openid;
        try {
            openid = HttpClient.getWxUserOpenid(account.get("code").toString(), appId, secret).get("openid").toString();
        } catch (Exception e) {
            responseModel = new ResponseModel(199, "微信授权失败");
            return responseModel;
        }
        UserInfo userInfo = iUserInfoService.loginUser(openid);
        Map<String, Object> map = new HashMap<>(2);
        if (userInfo != null) {
            //判断该用户token是否为空
            userInfo.setOpenid(openid);
            if (userInfo.getToken() == null || "".equals(userInfo.getToken())) {
                String token = TokenUtil.createToken(userInfo.getUid(), userInfo.getOpenid(), 1000 * 60L);
                userInfo.setToken(token);
                //token存入用户数据库
                iUserInfoService.updateToken(userInfo.getUid(), token);
            } else {
                if (!TokenUtil.decodeToken(userInfo.token)) {
                    String token = TokenUtil.createToken(userInfo.getUid(), userInfo.getOpenid());
                    userInfo.setToken(token);
                    //token存入用户数据库
                    iUserInfoService.updateToken(userInfo.getUid(), token);
                }
            }
            userInfo = iUserInfoService.loginUser(openid);
            userInfo.setOpenid(openid);
            map.put("uid", userInfo.getUid());
            map.put("isFirstLogin",false);
            map.put("token", userInfo.getToken());
            responseModel = new ResponseModel(200, "登录成功", map);
        } else {
            String uid = getId(length);
            userInfo = new UserInfo();
            String token = TokenUtil.createToken(uid, openid);
            userInfo.setToken(token);
            userInfo.setUid(uid);
            iUserInfoService.addUser(uid, openid, token);
            userInfo = iUserInfoService.loginUser(openid);
            map.put("uid", userInfo.getUid());
            map.put("isFirstLogin",true);
            map.put("token", userInfo.getToken());
            responseModel = new ResponseModel(200, "登录成功", map);
        }
        return responseModel;
    }

    @RequestMapping(value = "/active", method = RequestMethod.GET)
    public ResponseModel active() {
        int alreadyActivate = 90114;
        ResponseModel responseModel;
        int errorCode = arcSoftFace.activeOnline();
        if (errorCode == 0) {
            responseModel = new ResponseModel(200, "激活成功", errorCode);
        } else if (errorCode == alreadyActivate) {
            responseModel = new ResponseModel(181, "已激活，请勿重复激活", errorCode);
        } else {
            responseModel = new ResponseModel(189, "激活失败", errorCode);
        }
        return responseModel;
    }

    @RequestMapping(value = "/addFace", method = RequestMethod.POST)
    @CurrentLimiter(QPS = 5)
    public ResponseModel addFace(@RequestBody() JSONObject jsonObject) {
        ResponseModel responseModel;
        try {
            File file = base64ToFile(jsonObject.getString("file"));
            List<FaceInfo> faceInfoList = arcSoftFace.detectFaces(file);
            FaceFeature faceFeature = new FaceFeature(arcSoftFace.extractFaceFeature(file, faceInfoList));
            if (faceFeature.getFeatureData() == null) {
                return new ResponseModel(188, "添加人脸失败，未检测到人脸");
            }
            iUserInfoService.addFace(jsonObject.getString("uid"), faceFeature.getFeatureData());
            if (arcSoftFace.getLiveness() != 1) {
                responseModel = new ResponseModel(184, "活体检测不成功", "活体检测结果：" + arcSoftFace.getLiveness());
            } else {
                responseModel = new ResponseModel(200, "添加人脸成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
            responseModel = new ResponseModel(188, "添加人脸失败，未检测到人脸");
        }
        return responseModel;
    }

    @RequestMapping(value = "/compareFace", method = RequestMethod.POST)
    @CurrentLimiter(QPS = 5)
    public ResponseModel compareFaceFeature(@RequestBody() JSONObject jsonObject) {
        ResponseModel responseModel;
        try {
            byte[] bytes = iUserInfoService.selectFaceFeature(jsonObject.getString("uid"));
            if (bytes == null) {
                return new ResponseModel(185, "没有此用户的人脸信息");
            }
            File file = base64ToFile(jsonObject.getString("file"));
            FaceFeature targetFaceFeature = new FaceFeature(bytes);
            List<FaceInfo> faceInfoList = arcSoftFace.detectFaces(file);
            byte[] bytes1 = arcSoftFace.extractFaceFeature(file, faceInfoList);
            if (bytes1 == null) {
                return new ResponseModel(186, "上传的图片没有识别到人脸信息");
            }
            FaceFeature sourceFaceFeature = new FaceFeature(bytes1);
            float result = arcSoftFace.compareFaceFeature(targetFaceFeature, sourceFaceFeature);
            if (arcSoftFace.getLiveness() != 1) {
                responseModel = new ResponseModel(183, "活体检测不成功", "活体检测结果：" + arcSoftFace.getLiveness());
            } else {
                responseModel = new ResponseModel(200, "对比成功", result);
            }
        } catch (Exception e) {
            e.printStackTrace();
            responseModel = new ResponseModel(187, "对比失败，未检测到人脸", 0);
        }
        return responseModel;
    }


    private File base64ToFile(String base64) {
        int length = 15;
        int minLength = 3;
        final String tempPath = "C:\\tmp\\";
        File file = null;
        FileOutputStream out = null;
        try {
            // 解码，然后将字节转换为文件
            boolean isCreateSuccess = false;
            String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            Random random = new Random();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++) {
                int number = random.nextInt(62);
                sb.append(str.charAt(number));
            }
            String fileName = sb.toString() + ".jpg";
            file = new File(tempPath + fileName);
            if (!file.exists()) {
                isCreateSuccess = file.createNewFile();
            }
            // 将字符串转换为byte数组
            byte[] bytes = Base64.decode(base64);
            ByteArrayInputStream in = new ByteArrayInputStream(bytes);
            byte[] buffer = new byte[1024];
            for (int j = 0; j < minLength; j++) {
                if (!isCreateSuccess) {
                    for (int i = 0; i < length; i++) {
                        int number = random.nextInt(62);
                        sb.append(str.charAt(number));
                    }
                    fileName = sb.toString() + ".jpg";
                    file = new File(tempPath + fileName);
                    if (!file.exists()) {
                        isCreateSuccess = file.createNewFile();
                    }
                } else {
                    break;
                }
            }
            if (!isCreateSuccess) {
                return null;
            }
            out = new FileOutputStream(file);
            int byteRead;
            while ((byteRead = in.read(buffer)) != -1) {
                // 文件写操作
                out.write(buffer, 0, byteRead);
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    private String getId(int length){
        StringBuilder stringBuilder = new StringBuilder();
        Random random = new Random();
        for (int x = 0; x < length; x++) {
            stringBuilder.append(String.valueOf(random.nextInt(10)));
        }
        return stringBuilder.toString();
    }
}
